"""
基础模型定义
===========
提供所有业务模型的基础类和常用混入
"""

import uuid
from datetime import datetime
from typing import Optional, Any, Dict
from pydantic import BaseModel as PydanticBaseModel, Field, ConfigDict


class BaseModel(PydanticBaseModel):
    """基础模型类"""
    
    model_config = ConfigDict(
        # 允许额外字段
        extra='forbid',
        # 使用枚举值而不是名称
        use_enum_values=True,
        # 验证赋值
        validate_assignment=True,
        # 序列化时使用别名
        populate_by_name=True,
        # JSON编码器配置
        json_encoders={
            datetime: lambda v: v.isoformat() if v else None,
            uuid.UUID: lambda v: str(v) if v else None
        }
    )
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return self.model_dump(exclude_none=True)
    
    def to_json(self) -> str:
        """转换为JSON字符串"""
        return self.model_dump_json(exclude_none=True)
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]):
        """从字典创建实例"""
        return cls(**data)


class UUIDMixin(BaseModel):
    """UUID混入"""
    
    id: Optional[str] = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="唯一标识符",
        example="550e8400-e29b-41d4-a716-446655440000"
    )


class TimestampMixin(BaseModel):
    """时间戳混入"""
    
    created_at: Optional[datetime] = Field(
        default_factory=datetime.utcnow,
        description="创建时间"
    )
    
    updated_at: Optional[datetime] = Field(
        default_factory=datetime.utcnow,
        description="更新时间"
    )
    
    def update_timestamp(self):
        """更新时间戳"""
        self.updated_at = datetime.utcnow()


class SoftDeleteMixin(BaseModel):
    """软删除混入"""
    
    is_deleted: bool = Field(
        default=False,
        description="是否已删除"
    )
    
    deleted_at: Optional[datetime] = Field(
        default=None,
        description="删除时间"
    )
    
    def soft_delete(self):
        """软删除"""
        self.is_deleted = True
        self.deleted_at = datetime.utcnow()
    
    def restore(self):
        """恢复"""
        self.is_deleted = False
        self.deleted_at = None


class VersionMixin(BaseModel):
    """版本控制混入"""
    
    version: int = Field(
        default=1,
        description="版本号"
    )
    
    def increment_version(self):
        """增加版本号"""
        self.version += 1
